#!/usr/bin/env python3
"""
生成测试管理相关数据的脚本
生成测试用例文件夹、测试用例、测试计划、测试报告等数据
"""

import asyncio
import sys
import os
from datetime import datetime, timedelta, timezone
from bson import ObjectId
from motor.motor_asyncio import AsyncIOMotorClient
import random

# 添加项目根目录到Python路径
sys.path.append(os.path.dirname(os.path.abspath(__file__)))

from app.core.config import settings
from app.models.test_case import (
    TestCaseType, TestCasePriority, TestCaseCategory, ExecutionResult,
    TestCaseStep, TestCaseBase, TestPlanStatus
)

async def generate_test_data():
    """生成测试管理相关数据"""
    client = None
    
    try:
        # 连接到MongoDB
        client = AsyncIOMotorClient(settings.MONGODB_URL)
        db = client[settings.MONGODB_DATABASE]
        
        print("开始生成测试管理相关数据...")
        
        # 获取现有项目和用户ID，用于关联
        projects = await db.projects.find().to_list(length=10)
        if not projects:
            print("❌ 未找到项目数据，请先创建项目")
            return
        
        project_ids = [p["_id"] for p in projects]
        users = await db.users.find().to_list(length=10)
        user_ids = [u["_id"] for u in users] if users else [ObjectId()]
        
        now = datetime.now(timezone.utc)
        
        # 1. 生成测试用例文件夹（树形结构）
        print("\n1. 生成测试用例文件夹...")
        folders = []
        root_folders = []
        
        # 为每个项目创建根文件夹
        for project_id in project_ids[:3]:  # 只为前3个项目创建文件夹
            # 创建根文件夹
            root_folder = {
                "_id": ObjectId(),
                "name": f"项目测试用例库",
                "description": "项目测试用例根目录",
                "project_id": project_id,
                "parent_id": None,
                "creator_id": user_ids[0],
                "sort_order": 0,
                "created_at": now,
                "updated_at": now
            }
            root_folders.append(root_folder)
            folders.append(root_folder)
            
            # 为每个根文件夹创建子文件夹
            sub_folder_names = ["功能测试", "性能测试", "安全测试", "兼容性测试"]
            for idx, sub_name in enumerate(sub_folder_names):
                sub_folder = {
                    "_id": ObjectId(),
                    "name": sub_name,
                    "description": f"{sub_name}用例目录",
                    "project_id": project_id,
                    "parent_id": root_folder["_id"],
                    "creator_id": user_ids[0],
                    "sort_order": idx,
                    "created_at": now,
                    "updated_at": now
                }
                folders.append(sub_folder)
        
        if folders:
            await db.test_case_folders.insert_many(folders)
            print(f"✅ 成功生成 {len(folders)} 个测试用例文件夹")
        
        # 2. 生成测试用例
        print("\n2. 生成测试用例...")
        test_cases = []
        folder_ids = [f["_id"] for f in folders]
        
        for i in range(50):
            # 随机选择项目和文件夹
            project_id = random.choice(project_ids)
            folder_id = random.choice(folder_ids) if folder_ids else None
            
            # 生成测试步骤
            steps = []
            step_count = 2 + i % 5  # 2-6个步骤
            for step in range(step_count):
                steps.append(TestCaseStep(
                    step_number=step + 1,
                    action=f"执行步骤 {step + 1}：测试功能点 {i + 1}",
                    expected_result=f"预期结果 {step + 1}：功能点 {i + 1} 正常工作"
                ))
            
            # 创建测试用例
            test_case = TestCaseBase(
                title=f"测试用例 #{i + 1}: 系统功能测试",
                description=f"详细描述测试用例 #{i + 1}，用于测试系统的核心功能",
                preconditions="系统已启动，用户已登录",
                test_steps=steps,
                expected_result=f"所有测试步骤执行成功，系统功能正常",
                postconditions="测试完成，系统状态保持稳定",
                type=TestCaseType.FUNCTIONAL if i % 2 == 0 else TestCaseType.REGRESSION,
                category=TestCaseCategory.POSITIVE if i % 3 == 0 else TestCaseCategory.NEGATIVE,
                status="ready",
                priority=random.choice(list(TestCasePriority)),
                project_id=str(project_id),
                folder_id=str(folder_id) if folder_id else None,
                tags=[f"功能测试", f"系统测试", f"测试用例-{i + 1}"],
                estimated_duration=10 + i % 30  # 10-39分钟
            )
            
            # 转换为可插入MongoDB的字典
            test_case_dict = test_case.model_dump(by_alias=True, exclude_none=True)
            test_case_dict["_id"] = ObjectId()
            test_case_dict["project_id"] = project_id
            if folder_id:
                test_case_dict["folder_id"] = folder_id
            test_case_dict["creator_id"] = user_ids[0]
            test_case_dict["created_at"] = now
            test_case_dict["updated_at"] = now
            
            test_cases.append(test_case_dict)
        
        if test_cases:
            await db.test_cases.insert_many(test_cases)
            print(f"✅ 成功生成 {len(test_cases)} 条测试用例数据")
        
        # 3. 生成测试计划
        print("\n3. 生成测试计划...")
        test_plans = []
        test_case_ids = [tc["_id"] for tc in test_cases]
        
        for i in range(5):
            project_id = random.choice(project_ids)
            # 随机选择一些测试用例
            selected_case_ids = random.sample(test_case_ids, min(10, len(test_case_ids)))
            
            start_date = now + timedelta(days=i * 7)
            end_date = start_date + timedelta(days=14)
            
            test_plan = {
                "_id": ObjectId(),
                "name": f"测试计划 #{i + 1}",
                "description": f"测试计划 #{i + 1} 的详细描述",
                "project_id": project_id,
                "start_date": start_date,
                "end_date": end_date,
                "status": random.choice(["pending", "executing", "completed"]),
                "test_case_ids": selected_case_ids,
                "pass_rate": random.uniform(70, 100) if i > 2 else None,
                "created_by": user_ids[0],
                "created_at": now - timedelta(days=30 - i * 5),
                "updated_at": now - timedelta(days=30 - i * 5)
            }
            test_plans.append(test_plan)
        
        if test_plans:
            await db.test_plans.insert_many(test_plans)
            print(f"✅ 成功生成 {len(test_plans)} 个测试计划")
        
        # 4. 生成测试计划执行记录
        print("\n4. 生成测试计划执行记录...")
        executions = []
        
        for plan in test_plans[:3]:  # 只为前3个计划生成执行记录
            if plan["status"] in ["executing", "completed"]:
                plan_case_ids = plan["test_case_ids"][:5]  # 每个计划执行5个用例
                for case_id in plan_case_ids:
                    execution = {
                        "_id": ObjectId(),
                        "test_plan_id": plan["_id"],
                        "test_case_id": case_id,
                        "execution_result": random.choice(["passed", "failed", "blocked", "skipped"]),
                        "executed_by": user_ids[0],
                        "execution_date": plan["start_date"] + timedelta(days=random.randint(1, 10)),
                        "notes": f"执行备注：测试用例执行完成",
                        "attachments": [],
                        "created_at": now,
                        "updated_at": now
                    }
                    executions.append(execution)
        
        if executions:
            await db.test_plan_executions.insert_many(executions)
            print(f"✅ 成功生成 {len(executions)} 条测试计划执行记录")
        
        # 5. 生成测试报告
        print("\n5. 生成测试报告...")
        test_reports = []
        
        for plan in test_plans[:2]:  # 只为前2个计划生成报告
            if plan["status"] == "completed":
                # 计算报告数据
                plan_executions = [e for e in executions if e["test_plan_id"] == plan["_id"]]
                total = len(plan_executions)
                passed = len([e for e in plan_executions if e["execution_result"] == "passed"])
                failed = len([e for e in plan_executions if e["execution_result"] == "failed"])
                blocked = len([e for e in plan_executions if e["execution_result"] == "blocked"])
                skipped = len([e for e in plan_executions if e["execution_result"] == "skipped"])
                
                report_data = {
                    "total": total,
                    "passed": passed,
                    "failed": failed,
                    "blocked": blocked,
                    "skipped": skipped,
                    "pass_rate": round((passed / total * 100), 2) if total > 0 else 0
                }
                
                report = {
                    "_id": ObjectId(),
                    "name": f"{plan['name']} - 测试报告",
                    "test_plan_id": plan["_id"],
                    "version_id": None,  # 手动关联
                    "file_path": None,
                    "report_data": report_data,
                    "generated_at": plan["end_date"],
                    "created_by": user_ids[0],
                    "created_at": plan["end_date"],
                    "updated_at": plan["end_date"]
                }
                test_reports.append(report)
        
        if test_reports:
            await db.test_reports.insert_many(test_reports)
            print(f"✅ 成功生成 {len(test_reports)} 个测试报告")
        
        # 验证生成结果
        print("\n📊 数据生成完成，验证结果:")
        folder_count = await db.test_case_folders.count_documents({})
        test_case_count = await db.test_cases.count_documents({})
        plan_count = await db.test_plans.count_documents({})
        execution_count = await db.test_plan_executions.count_documents({})
        report_count = await db.test_reports.count_documents({})
        
        print(f"  测试用例文件夹: {folder_count} 个")
        print(f"  测试用例: {test_case_count} 条")
        print(f"  测试计划: {plan_count} 个")
        print(f"  测试计划执行记录: {execution_count} 条")
        print(f"  测试报告: {report_count} 个")
        
        print("\n✅ 所有测试管理相关数据已生成完成！")
        
    except Exception as e:
        print(f"❌ 生成数据失败: {e}")
        import traceback
        traceback.print_exc()
    finally:
        # 关闭连接
        if client:
            await client.close()

if __name__ == "__main__":
    asyncio.run(generate_test_data())
